package com.agile.leetcode.jvm.objectreference;

import java.lang.ref.WeakReference;

/**
 * 当垃圾收集器开始工作，无论当前内存是否足够，都会回收只被弱引用关联的对象。
 * 因此，被弱引用关联的对象只能生存到下一次垃圾收集发生为止。
 * 使用场景:
 * 如果一个对象是偶尔(很少)使用，并且希望在使用时随时就能获取到，但又不想影响此对象的垃圾收集，那么你可以使用 WeakReference来记住此对象。
 * 但是使用弱引用也会带来一些额外的问题：
 * 弱引用会使代码更加复杂，并且可能容易出错。任何使用弱引用的代码都需要处理每次使用弱引用时引用被破坏的可能性。如果过度使用弱引用，最终会编写大量额外代码。
 * 使用弱引用会带来运行时开销。显而易见的代价是创建弱引用并调用 get 。一个不太明显的代价是每次 GC 运行时都需要做大量额外的工作。
 * 如果对应用程序将来很可能需要的东西使用弱引用，则可能会导致重复创建它的成本。如果这一成本很高（在CPU时间、IO带宽、网络流量等方面）），
 * 可能会在一定程度上影响系统的吞吐量。此时，最好给 JVM 更多的内存，而不是使用弱引用。
 *
 * @Author:ChenZhangKun
 * @Date: 2021/10/11 22:37
 */
public class WeakReferenceDemo {
    public static void main(String[] args) throws InterruptedException {
        // 此处代码先创建了一个Object类型的对象，
        // 然后使用WeakReference对这个新建对象进行 “描述包装”，
        // 如此这个新建对象就只处于弱引用状态
        WeakReference<Object> weakReference = new WeakReference<>(new Object());
        // 处于弱引用状态的对象，可以使用WeakReference对象的get方法获取
        // 如果不想给对象添加其他引用状态，那么只可以使用WeakReference对象的get方法获取
        // WeakReference对象的get方法的返回值 就好比 强引用状态中的变量名
        // 强引用状态中的变量名如何使用，那么WeakReference对象的get方法的返回值就如何使用
        System.out.println(weakReference.get());
        // 主动开启JVM的GC
        System.gc();
        // 注意：实际上 JVM 何时进行 GC 操作并不可控！
        // 我们调用System.gc()方法只是起通知作用，JVM 什么时候扫描回收对象是 JVM 自己根据当前系统的状态决定的。
        // 因此更严谨的做法是休眠等待一段时间再验证 GC 的情况
        Thread.sleep(5000);
        // 输出为null
        // 因为GC将只处于弱引用的对象给回收掉了，
        // 所以WeakReference对象无法再引用到之前的 “描述包装” 的对象了
        System.out.println(weakReference.get());
    }
}
